﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Xml.XPath;
using System.Text.RegularExpressions;

namespace ComicsEditor
{
    public partial class PageEditor : UserControl
    {
        public Page Page;

        public FrameSelectInstrument FrameSelect = new FrameSelectInstrument();
        public FrameDrawInstrument FrameDraw = new FrameDrawInstrument();
        public FrameOrderInstrument FrameOrder = new FrameOrderInstrument();
        public BalloonSelectInstrument BalloonSelect = new BalloonSelectInstrument();
        public BalloonFillInstrument BalloonFill = new BalloonFillInstrument();
        public BalloonRectInstrument BalloonRect = new BalloonRectInstrument();
        public BalloonCircleInstrument BalloonCircle = new BalloonCircleInstrument();
        public TextSelectInstrument TextSelect = new TextSelectInstrument();
        public TextWriteInstrument TextWrite = new TextWriteInstrument();

        private Image img = null;
        private float scale;

        private RectangleF rectPage;
        private Bitmap imgResized;
        private PointF pointOffset;
        private SizeF sizeOffset;

        private bool bMouseDown;
        private Point pointMouse;
        private Point pointMouseMove;

        public PageEditor()
        {
            InitializeComponent();

            this.SetStyle(System.Windows.Forms.ControlStyles.ResizeRedraw, true);
            this.SetStyle(System.Windows.Forms.ControlStyles.UserPaint, true);
            this.SetStyle(System.Windows.Forms.ControlStyles.AllPaintingInWmPaint, true);
            this.SetStyle(System.Windows.Forms.ControlStyles.OptimizedDoubleBuffer, true);
        }

        public void Reset()
        {
            img = null;
            Page = null;
            rectPage = RectangleF.Empty;
            Invalidate();
        }

        public void SetPageInfo(PageInfo PageInfo)
        {
            Page = PageInfo.Page;
            img = PageInfo.Image;

            /*Text text = new Text(Page, new Point(img.Width/2, img.Height/2));
            text.Fill = new SolidBrush(Color.White);
            text.FontSize = 25;
            text.AddLine("pTESTバカ");
            text.AddLine("Сырно — バカ2");
            text.AddLine("مُـحمَّـد مُحمَّد");
            //text.Lines[0].SetFontSize(0, 2, 50);
            //text.Lines[1].SetFontSize(0, 3, 50);
            //text.Lines[2].SetFontName(0, text.Lines[2].Count, "Courier New");
            //text.Baseline = "middle";
            //text.Baseline = "text-before-edge";
            //text.Baseline = "text-after-edge";
            //text.Vertical = true;
            text.RightToLeft = true;
            //text.RotateDegrees = 45;
            //text.Aligment = StringAlignment.Center;
            text.Rebuild();
            text.BeginEdit();*/

            FrameSelect.Bind(PageInfo);
            FrameDraw.Bind(PageInfo);
            FrameOrder.Bind(PageInfo);
            BalloonSelect.Bind(PageInfo);
            BalloonFill.Bind(PageInfo);
            BalloonRect.Bind(PageInfo);
            BalloonCircle.Bind(PageInfo);
            TextSelect.Bind(PageInfo);
            TextWrite.Bind(PageInfo);

            scale = 1;
            sizeOffset.Width = Page.Width*scale - Size.Width;
            sizeOffset.Height = Page.Height*scale - Size.Height;
            pointOffset = PointF.Empty;
            Scale = Size.Height/(float)Page.Height;

            Invalidate();
        }

        public new float Scale
        {
            get
            {
                return scale;
            }
            set
            {
                if (Page != null)
                {
                    if (sizeOffset.Width > 0)
                        pointOffset.X /= sizeOffset.Width;
                    if (sizeOffset.Height > 0)
                        pointOffset.Y /= sizeOffset.Height;
                    sizeOffset.Width += Page.Width*value - Page.Width*scale;
                    sizeOffset.Height += Page.Height*value - Page.Height*scale;
                    pointOffset.X *= sizeOffset.Width > 0 ? sizeOffset.Width : 0;
                    pointOffset.Y *= sizeOffset.Height > 0 ? sizeOffset.Height : 0;
                    rectPage = new RectangleF(Size.Width/2 - Page.Width*value/2 - pointOffset.X, Size.Height/2 - Page.Height*value/2 - pointOffset.Y, Page.Width*value, Page.Height*value);
                    Page.Output = rectPage;
                    scale = value;
                    UpdateImage();
                    Invalidate();
                }
            }
        }

        public void UpdatePage()
        {
            if (Page.Changed)
                Invalidate();
        }

        private void UpdateImage()
        {
            if (scale <= 2.0f && img != null)
            {
                imgResized = new Bitmap((int)rectPage.Width, (int)rectPage.Height);
                Graphics g = Graphics.FromImage(imgResized);
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                g.DrawImage(img, 0, 0, rectPage.Width, rectPage.Height);
                g.Dispose();
            }
            else
                imgResized = null;
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            e.Graphics.Clear(Color.Gray);

            if (Page != null)
            {
                e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
                if (imgResized != null)
                    e.Graphics.DrawImage(imgResized, (int)rectPage.X, (int)rectPage.Y);
                else if (img != null)
                    e.Graphics.DrawImage(img, rectPage);

                e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                e.Graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.Default;
                e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                Page.Draw(e.Graphics);
            }
        }

        private void PageEditor_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                if (Page != null && Page.OnMouseDown(new PointF(e.X, e.Y)))
                {
                    UpdatePage();
                }
                else if (rectPage.Contains(e.X, e.Y))
                {
                    bMouseDown = true;
                    pointMouse = e.Location;
                    pointMouseMove = e.Location;
                }
            }
        }

        private void PageEditor_MouseUp(object sender, MouseEventArgs e)
        {
            if (Page != null)
            {
                Page.OnMouseUp();
                UpdatePage();
            }
            if (bMouseDown)
            {
                bMouseDown = false;
            }
        }

        private void PageEditor_MouseMove(object sender, MouseEventArgs e)
        {
            if (Page != null)
            {
                Page.OnMouseMove(new PointF(e.X, e.Y));
                UpdatePage();
            }
            if (bMouseDown)
            {
                SizeF offEff = sizeOffset;
                if (offEff.Width < 0)
                    offEff.Width = 0;
                if (offEff.Height < 0)
                    offEff.Height = 0;
                pointOffset.X += pointMouseMove.X - e.X;
                pointOffset.Y += pointMouseMove.Y - e.Y;
                if (pointOffset.X < -offEff.Width/2)
                    pointOffset.X = -offEff.Width/2;
                if (pointOffset.Y < -offEff.Height/2)
                    pointOffset.Y = -offEff.Height/2;
                if (pointOffset.X > offEff.Width/2)
                    pointOffset.X = offEff.Width/2;
                if (pointOffset.Y > offEff.Height/2)
                    pointOffset.Y = offEff.Height/2;
                rectPage = new RectangleF(Size.Width/2 - Page.Width*scale/2 - pointOffset.X, Size.Height/2 - Page.Height*scale/2 - pointOffset.Y, Page.Width*scale, Page.Height*scale);
                Page.Output = rectPage;
                Invalidate();

                pointMouseMove = e.Location;
            }
        }
    }
}
